import json
import os.path
import threading
import re
import time

from .compBase import TBaseComp
class TBucket:
    def __init__(self , io):
        self.bucketCode = ""
        self.bucketType="kv"  #kv ,  file , oss , redis
        self.bucketLock = threading.Lock()
        self.bucketInfo = {}
        self.itemLocks ={}
        self.io = io
    def write(self , key , value ):
        try:
            pass
        except Exception as er:
            print(er)
    def writeBatch(self , dictKeyValue ):
        try:
            pass
        except Exception as er:
            print(er)
    def read(self , keyList ):
        res=None
        try:
            pass
        except Exception as er:
            print(er)
        return  res
    def remove(self , keyList ):
        res={}
        try:
            pass
        except Exception as er:
            print(er)
        return res
    def getKeys(self , keyPatter , flag=0 ):
        res=[]
        try:
            pass
        except Exception as er:
            print(er)
        return  res

    def loadBucket(self):
        try:
            pass
        except Exception as er:
            print(er)
    def saveBucket(self):
        try:
            pass
        except Exception as er:
            print(er)
class TFileBucket( TBucket):
    def __init__(self, io):
        super().__init__(io)
        self.bucketType = "file"
    def write(self , key , value ):
        res = 0
        try:
            rootPath = self.bucketInfo['rootPath']
            fn = os.path.join(rootPath , key)
            fnDir = os.path.dirname(fn)
            if not os.path.exists(fnDir):
                os.makedirs(fnDir , 0x777)
            with open(fn , 'w' , encoding='utf-8') as f :
                f.write(str(value))
            res = 1 if os.path.exists(fn) else 0
        except Exception as er:
            print(er)
    def writeBatch(self , dictKeyValue ):
        try:
            result = {}
            for key in dictKeyValue.keys():
                value = dictKeyValue[key]
                result[key] = self.write(key , value)
            res = result
        except Exception as er:
            print(er)
    def read(self , keyList ):
        res=None
        try:
            result = {}
            for key in keyList:
                rootPath = self.bucketInfo['rootPath']
                fn = os.path.join(rootPath , key)
                c = None
                if os.path.exists(fn):
                    with open(fn , 'w' , encoding='utf-8') as f :
                        c = f.read()
                result[key] = c
            res = result
        except Exception as er:
            print(er)
        return  res
    def remove(self , keyList ):
        res={}
        try:
            result = {}
            for key in keyList:
                rootPath = self.bucketInfo['rootPath']
                fn = os.path.join(rootPath , key)
                flag = 0
                if os.path.exists(fn):
                    try:
                        os.remove( fn)
                        flag = 1
                    except Exception as ee:
                        print(ee)
                else:
                    flag = 2
                result[key]= flag
            res = result
        except Exception as er:
            print(er)
        return res
    def getKeys(self , keyPatter , flag=0 ):
        res=[]
        try:
            pass
        except Exception as er:
            print(er)
        return  res
class TOssBucket( TBucket):
    def __init__(self, io):
        super().__init__(io)
        self.bucketType = "oss"
class TRedisBucket( TBucket):
    def __init__(self, io):
        super().__init__(io)
        self.bucketType = "redis"
class TKvBucket( TBucket):
    def __init__(self, io):
        super().__init__(io)
        self.bucketType = "kv"
        self.kvs ={}
        self.lastSaveTime = 0
        self.active = False
        self.dataChanged = False
    def write(self , key , value ):
        try:
            self.kvs[key] = value
            #print(key, value)
        except Exception as er:
            print(er)
    def writeBatch(self , dictKeyValue ):
        try:
            for k , v in dictKeyValue.items():
                self.write(k,v)
        except Exception as er:
            print(er)
    def read(self , keyList ):
        res={}
        try:
            ks = self.kvs.keys()
            for k in keyList:
                v = {}
                if k in ks:
                    v = self.kvs[k]
                res[k] = v
        except Exception as er:
            print(er)
        print(res)
        return  res
    def remove(self , keyList ):
        res={}
        try:
            for k in keyList:
                if k in  self.kvs.keys():
                    self.kvs.pop(k)
        except Exception as er:
            print(er)
        return res
    def getKeys(self , keyPatter , flag=0 ):
        res=[]
        try:
            res =list( self.kvs.keys())
        except Exception as er:
            print(er)
        return  res

    def loadBucket(self):
        try:
            fn = self.bucketInfo['dataPath']
            if  os.path.exists(fn):
                with open( fn , 'r' , encoding='utf-8') as f :
                    try:
                        self.kvs = json.loads(f.read())
                    except Exception as eer:
                        print(eer)
            self.saveThread = threading.Thread(target= self.loopSave , daemon= True)
            self.active = True
            self.dataChanged = False
            self.saveThread.start()

        except Exception as er:
            print(er)
    def loopSave(self):
        try:
            timeThreshold = self.bucketInfo['saveTime']
            fn = self.bucketInfo['dataPath']
            dirName = os.path.dirname(fn)
            if not os.path.exists(dirName):
                os.makedirs(dirName , 0x777)
            while self.active:
                try:
                    time.sleep(10)
                    nt = time.time()
                    if self.dataChanged  and  (self.lastSaveTime + timeThreshold < nt):
                        with open ( fn , 'w' , encoding='utf-8') as f:
                            try:
                                f.write(json.dumps(self.kvs))
                            except Exception as erf:
                                print(erf, fn)
                        self.dataChanged = False
                        self.lastSaveTime = nt
                except Exception as err:
                    print(err)
        except Exception as er:
            print(er)
    def saveBucket(self):
        try:
            fn = self.bucketInfo['dataPath']
            dirName = os.path.dirname(fn)
            if not os.path.exists(dirName):
                os.makedirs(dirName , 0x777)
            nt = time.time()
            with open(fn, 'w', encoding='utf-8') as f:
                try:
                    f.write(json.dumps(self.kvs))
                except Exception as erf:
                    print(erf, fn)
            self.dataChanged = False
            self.lastSaveTime = nt
        except Exception as er:
            print(er)
class TCompIo(TBaseComp):
    def __init__(self):
        super().__init__()
        self.componentKey = 'io'
        self.buckets={}
        self.handlers={
            "set" : self.set ,
            "setBatch" : self.setBatch,
            "remove" : self.remove ,
            "get" : self.get ,
            "getKeys" : self.getKeys
        }
    def doOnSetSettings(self):
        try:
            super().doOnSetSettings()
            self.loadAllBucket()
        except Exception as er:
            print(er)
    def loadAllBucket(self):
        res = None
        try:
            for bc in self.settings.keys():
                self.loadBucket(bc)
        except Exception as er:
            print(er)
        return  res
    def loadBucket(self, bucketCode):
        res = None
        try:
            print(f'load io :{bucketCode}')
            res = self.getBucket(bucketCode)
            res.loadBucket()
        except Exception as er:
            print(er)
        return  res
    def getBucket(self, bucketCode):
        res = None
        try:
            if bucketCode in self.buckets.keys():
                res = self.buckets[bucketCode]
            elif bucketCode in self.settings.keys():
                bucketType = self.settings[bucketCode]['bucketType']
                bucketInfo = self.settings[bucketCode]['bucketInfo']
                if bucketType =='file':
                    res = TFileBucket(self)
                elif bucketType =='oss':
                    res = TOssBucket(self)
                elif bucketType =='redis':
                    res = TRedisBucket(self)
                elif bucketType =='kv':
                    res = TKvBucket(self)
                if res !=None:
                    res.bucketCode = bucketCode
                    res.bucketInfo = bucketInfo
                    res.loadBucket()
                    self.buckets[res.bucketCode] = res
        except Exception as er:
            print(er)
        return  res
    def set(self , bucketCode , key , value):
        res=0
        try:
            bucket = self.getBucket(bucketCode)
            if bucket!=None:
                bucket.write(key , value)
                res = 1
            else:
                res = 0
        except Exception as er:
            print(er)
        return res
    def remove(self , bucketCode , keyList ):
        res = 0
        try:
            bucket = self.getBucket(bucketCode)
            if bucket!=None:
                bucket.remove(keyList)
                res = 1
            else:
                res = 0
        except Exception as er:
            print(er)
        return res
    def setBatch(self , bucketCode , dictKeyValue):
        res = 0
        try:
            bucket = self.getBucket(bucketCode)
            if bucket!=None:
                bucket.writeBatch(dictKeyValue)
                res = 1
            else:
                res = 0
        except Exception as er:
            print(er)
        return res
    def get(self , bucketCode , keyList):
        res={}
        try:
            bucket = self.getBucket(bucketCode)
            if bucket!=None:
                res = bucket.read(keyList)
            else:
                res = None
        except Exception as er:
            print(er)
        return res
    def getKeys(self , bucketCode , keyPatter , flag=0):
        res =[]
        try:
            bucket = self.getBucket(bucketCode)
            if bucket!=None:
                res = bucket.getKeys(keyPatter , flag)
            else:
                res = None
        except Exception as er:
            print(er)

compIo = TCompIo()
compIo.regist()

